package com.xlinur.android.moviecatalog;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Map;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;

public class MovieImportCSV extends Activity {
	private static final String PARSE_EXP = "(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
	private static final int SELECT_ID_OFFSET = 100;
	private static final int FILE_CHOOSE = 1;
	private static final int DIALOG_PROGRESS = 1;
	private static ProgressDialog mDialog;
	private static int[] mMap;
	private static int mMapLength;
	private static String mFilename;
	private static boolean mClearDB;
	private static boolean mIgnoreFirstrow;
	private static String mDivider;
	private static String mEncoding;
	private static BufferedReader mFile;
	private static String mLine;
	private static TextView eString;
	private static Button eButtonImport;
	private static Button eButtonCancel;
	private static EditText eFilename;
	private static Spinner eDivider;
	private static Spinner eEncoding;
	private static CheckBox eClearDB;
	private static CheckBox eIgnoreFirstrow;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.movie_import_csv);
		mMapLength = MovieCatalog.MovieOrder.length;
		mMap = new int[mMapLength];
		eString = (TextView) findViewById(R.id.csvTextView_string);
		eFilename = (EditText) findViewById(R.id.csvEditText_filename);
		eDivider = (Spinner) findViewById(R.id.csvSpinner_divider);
		eEncoding = (Spinner) findViewById(R.id.csvSpinner_encoding);
		eClearDB = (CheckBox) findViewById(R.id.csvCheckBox_cleardb);
		eIgnoreFirstrow = (CheckBox) findViewById(R.id.csvCheckBox_ignore_firstrow);
		eButtonImport = (Button) findViewById(R.id.csvButtonImport);
		eButtonCancel = (Button) findViewById(R.id.csvButtonCancel);

		eButtonImport.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				onImportButtonClicked();
			}
		});
		eButtonCancel.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				finish();
			}
		});
		eFilename.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				Intent viewActivity = new Intent(getBaseContext(),
						FileBrowser.class);
				viewActivity.putExtra("file", eFilename.getText().toString());
				startActivityForResult(viewActivity, FILE_CHOOSE);
			}
		});
		eDivider.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> parent, View view,
					int pos, long id) {
				showSelect();
			}

			public void onNothingSelected(AdapterView<?> arg0) {

			}

		});
		eEncoding.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> parent, View view,
					int pos, long id) {
				openFile();
			}

			public void onNothingSelected(AdapterView<?> arg0) {

			}

		});
		getPrefs();
		fillFields();
	}

	@Override
	public void onStart() {
		super.onStart();
		openFile();
	}

	@Override
	public void onStop() {
		super.onStop();
		if (mFile != null) {
			try {
				mFile.close();
			} catch (IOException e) {

			}
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == Activity.RESULT_OK && requestCode == FILE_CHOOSE) {
			String filename = data.getStringExtra("file");
			if (filename != null) {
				mFilename = filename;
				eFilename.setText(mFilename);
			}
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		super.onCreateDialog(id);
		switch (id) {
		case DIALOG_PROGRESS:
			ProgressDialog dialog = new ProgressDialog(this);
			dialog.setTitle(R.string.import_csv_progress_title);
			dialog.setMessage("");
			dialog.setIndeterminate(true);
			dialog.setCancelable(true);
			mDialog = dialog;
			return dialog;
		default:
			return null;
		}
	}

	private String readRow() throws IOException{
		String result = "";
		int numberOfQuotes = 1;
		while (numberOfQuotes % 2 != 0 ){
			String line = mFile.readLine(); 
			if (line!=null) {
				if (!"".equals(result)){
					result += "\n";
				}
				result += line;
				numberOfQuotes = result.replaceAll("[^\"]","").length();
			} else {
				if ("".equals(result)){
					result = null;
				}
				numberOfQuotes = 0;
			}
		}
		return result;
	}
	
	private void openFile() {
		mFile = null;
		mLine = null;
		eButtonImport.setEnabled(false);
		eString.setText("");
		((TableLayout) findViewById(R.id.csvTableLayout)).removeAllViews();
		boolean flag = false;
		try {
			mFile = new BufferedReader(new InputStreamReader(
					new FileInputStream(mFilename), eEncoding.getSelectedItem()
							.toString()));
			flag = true;
		} catch (UnsupportedEncodingException e1) {
			Toast.makeText(
					getApplicationContext(),
					getString(R.string.encoding_error)
							.replace("{1}", mFilename),
					MovieCatalog.MESSAGE_TIME).show();
		} catch (FileNotFoundException e1) {
			Toast.makeText(
					getApplicationContext(),
					getString(R.string.file_not_found)
							.replace("{1}", mFilename),
					MovieCatalog.MESSAGE_TIME).show();
		}
		if (flag) {
			try {
				mLine = readRow();
			} catch (IOException e) {
				mLine = null;
			}
			if (mLine==null){
				Toast.makeText(
					getApplicationContext(),
					getString(R.string.file_io_error).replace("{1}",
							mFilename), MovieCatalog.MESSAGE_TIME).show();
			} else {
				showSelect();
			}
		}
	}

	private void fillFields() {
		eFilename.setText(mFilename);
		eClearDB.setChecked(mClearDB);
		eIgnoreFirstrow.setChecked(mIgnoreFirstrow);
		String[] dividers = getResources().getStringArray(R.array.csvDivider);
		int count = dividers.length;
		for (int i = 0; i < count; i++) {
			if (dividers[i].equals(mDivider)) {
				eDivider.setSelection(i);
			}
		}
		String[] encoding = getResources().getStringArray(R.array.encoding);
		count = encoding.length;
		for (int i = 0; i < count; i++) {
			if (encoding[i].equals(mEncoding)) {
				eEncoding.setSelection(i);
			}
		}
	}

	private void getPrefs() {
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(getBaseContext());
		String pref;
		mFilename = prefs.getString("csvImportFilename", "");
		pref = prefs.getString("csvImportClearDB", "false");
		mClearDB = Boolean.parseBoolean(pref);
		pref = prefs.getString("csvIgnoreFirstrow", "false");
		mIgnoreFirstrow = Boolean.parseBoolean(pref);
		mDivider = prefs.getString("csvImportDivider", getResources()
				.getStringArray(R.array.csvDivider)[0]);
		mEncoding = prefs.getString("csvImportEncoding", getResources()
				.getStringArray(R.array.encoding)[2]);
		getMap();
	}

	private void getMap() {
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(getBaseContext());
		String mapStr = prefs.getString("csvImportMap", "1");
		String[] map = mapStr.split(",");
		int count = map.length;
		for (int i = 0; i < count; i++) {
			mMap[i] = Integer.parseInt(map[i]);
		}
		for (int i = count; i < mMapLength; i++) {
			mMap[i] = i + 1;
		}
	}

	private void setPrefs() {
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(getBaseContext());
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString("csvImportFilename", eFilename.getText().toString());
		editor.putString("csvImportClearDB", Boolean.toString(eClearDB.isChecked()));
		editor.putString("csvIgnoreFirstrow", Boolean.toString(eIgnoreFirstrow.isChecked()));
		editor.putString("csvImportDivider", eDivider.getSelectedItem()
				.toString());
		editor.putString("csvImportEncoding", eEncoding.getSelectedItem()
				.toString());
		String map = "";
		for (int i = 0; i < mMapLength; i++) {
			if (i > 0) {
				map += ",";
			}
			Spinner spin = (Spinner) findViewById(SELECT_ID_OFFSET + i);
			if (spin != null) {
				int spinItem = spin.getSelectedItemPosition();
				map += spinItem;
				mMap[i] = spinItem;
			} else {
				map += mMap[i];
			}
		}
		editor.putString("csvImportMap", map);
		editor.commit();
	}

	protected String[] parseString(String str) {
		String[] result = str.split(eDivider.getSelectedItem().toString()
				.replace("Tab", "\t")
				+ PARSE_EXP, 99);
		int count = result.length;
		for (int i = 0; i < count; i++) {
			String item = result[i];
			if (item.startsWith("\"") && item.endsWith("\"")) {
				item = item.substring(1, item.length() - 1);
			}
			item = item.replaceAll("\"\"", "\"");
			result[i] = item;
		}
		return result;
	}

	private void showSelect() {
		TableLayout table = (TableLayout) findViewById(R.id.csvTableLayout);
		table.removeAllViews();
		if (mLine != null) {
			eString.setText(mLine);
			String[] line = parseString(getString(R.string.import_csv_no_source)
					+ eDivider.getSelectedItem().toString()
							.replace("Tab", "\t") + mLine);
			int count = line.length;
			ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
					android.R.layout.simple_spinner_item, line);
			adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
			LayoutInflater linflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			for (int i = 0; i < mMapLength; i++) {
				TableRow row = (TableRow) linflater.inflate(
						R.layout.movie_import_csv_item, null);
				TextView dest = (TextView) row.findViewById(R.id.csvItemDest);
				dest.setText(getResources().getStringArray(R.array.movie)[i]);
				Spinner source = (Spinner) row.findViewById(R.id.csvItemSource);
				source.setId(SELECT_ID_OFFSET + i);
				source.setAdapter(adapter);
				if (mMap[i] < count) {
					source.setSelection(mMap[i]);
				} else {
					source.setSelection(0);
				}
				table.addView(row);
			}
			eButtonImport.setEnabled(true);
		}
	}

	private void onImportButtonClicked() {
		setPrefs();
		showDialog(DIALOG_PROGRESS);

		new Thread(new Runnable() {
			public void run() {
				final boolean complete = runImport();
				MovieImportCSV.this.runOnUiThread(new Runnable() {
					public void run() {
						dismissDialog(DIALOG_PROGRESS);
						if (complete) {
							Toast.makeText(getApplicationContext(),
									R.string.import_success,
									MovieCatalog.MESSAGE_TIME).show();
						} else {
							Toast.makeText(getApplicationContext(),
									R.string.import_fail,
									MovieCatalog.MESSAGE_TIME).show();
						}
						MovieList.mCursor.requery();
						finish();
					}
				});
			}
		}).start();
	}

	private boolean runImport() {
		if (eClearDB.isChecked()) {
			MovieCatalog.db.drop();
			MovieCatalog.db.create();
		}
		Map<String,String> data = null;
		int success = 0;
		int fail = 0;
		boolean flagFirstRow = true;
		while (mLine != null) {
			if (!flagFirstRow || !eIgnoreFirstrow.isChecked()) {
				data = MovieCatalog.db.getEmptyMovie();
				String[] line = parseString(mLine);
				int count = line.length + 1;
				for (int i = 0; i < mMapLength; i++) {
					int map = mMap[i];
					if (map == 0) {
						data.put(MovieCatalog.MovieOrder[i], null);
					} else {
						if (map < count) {
							data.put(MovieCatalog.MovieOrder[i],  line[map - 1]);
						} else {
							data.put(MovieCatalog.MovieOrder[i], "");
						}
					}
				}
				
				if (MovieCatalog.db.insertMovie(data, data.get("_id")) > 0) {
					success++;
				} else {
					fail++;
				}
				final String progressMessage = getString(
						R.string.import_csv_progress_message).replace("{1}",
						String.valueOf(success)).replace("{2}",
						String.valueOf(fail));
				MovieImportCSV.this.runOnUiThread(new Runnable() {
					public void run() {
						if (mDialog != null && mDialog.isShowing()) {
							mDialog.setMessage(progressMessage);
						}
					}
				});
			} else {
				flagFirstRow = false;
			}
			try {
				mLine = readRow();
			} catch (IOException e) {
				return false;
			}
		}
		return true;
	}
}
